package logic

import (
	"api/internal/svc"
	"api/internal/types"
	"api/model/discount"
	"api/model/discountmember"
	"api/service"
	"api/service/cert"
	"api/utils"
	"context"
	"encoding/json"
	"fmt"
	"github.com/go-pay/gopay/wechat/v3"
	"github.com/gorilla/websocket"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
	"strconv"
	"sync"

	"github.com/zeromicro/go-zero/core/logx"
)

type WxPayNotifyLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewWxPayNotifyLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WxPayNotifyLogic {
	return &WxPayNotifyLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

// 微信支付回调
func (l *WxPayNotifyLogic) WxPayNotify(req *types.RequestWxNotify) (resp *types.ResponseWxNotify, err error) {
	// 验签解密
	client, err := wechat.NewClientV3(cert.WxMchid, cert.WxSerialNo, cert.WxApiV3Key, cert.WxPrivateKey)
	if err != nil {
		l.Error("微信支付客户端实例化失败,无法处理微信回调.....", err)
		resp.Code = "fail"
		return resp, nil
	}

	// 启用自动同步返回验签，并定时更新微信平台API证书（开启自动验签时，无需单独设置微信平台API证书和序列号）
	err = client.AutoVerifySign()
	if err != nil {
		l.Error("微信支付客户端自动验签失败,无法处理微信回调.....", err)
		resp.Code = "fail"
		return resp, nil
	}

	ret, err := wechat.V3DecryptPartnerNotifyCipherText(req.Resource.Ciphertext, req.Resource.Nonce, req.Resource.AssociatedData, cert.WxApiV3Key)
	if err != nil {
		l.Error("微信支付回调验签失败,单号:"+ret.OutTradeNo, err)
		return &types.ResponseWxNotify{
			Code: "fail",
		}, nil
	}

	if ret.TradeState == "SUCCESS" {
		// 支付成功 修改订单状态
		orderService := service.NewOrderService(l.ctx, l.svcCtx)
		conn := sqlx.NewMysql(l.svcCtx.Config.DataSource)

		redis := l.svcCtx.RedisPool.Get()
		defer redis.Close()
		order := orderService.UpdateOrder(conn, redis, ret.OutTradeNo, service.ORDER_SUCCESS)

		// 分账
		if order != nil {
			// socket消息通知
			var wg sync.WaitGroup
			busService := service.NewBusinessService(l.ctx, l.svcCtx)

			result, _ := fmt.Printf("%.2f元\n", float64(order.Amount)/float64(100))

			voice := ""
			// 如果订单是会员购卡订单 则写入单据信息
			if order.CreateType == 2 {

				wg.Add(1)
				go func() {
					defer wg.Done()

					voice = "会员卡收入:" + strconv.Itoa(result)
					// 购卡订单
					discountModel := discount.NewDiscountModel(conn)
					d, err := discountModel.FindOne(l.ctx, int64(order.DiscountId))
					if err == nil {

						// 更改redis销量
						busService.SaveDiscountSale(redis, d.Id)

						discountMemberModel := discountmember.NewDiscountMemberModel(conn)
						discountInfo := &discountmember.DiscountMember{
							WxOpenId:   order.OpenId,
							BusinessId: int64(order.BusinessId),
							DiscountId: int64(order.DiscountId),
							Balance:    int64(d.Money),
							Discount:   int64(d.Discount),
							CreateAt:   utils.GetCurDateTime(),
							UpdateAt:   utils.GetCurDateTime(),
						}
						discountMemberModel.Insert(l.ctx, discountInfo)

					}
				}()

			}

			wg.Add(1)
			go func() {
				defer wg.Done()
				orderService.AliSplitBill(redis, order.BusinessId, order.TradeNo, order.InnerTradeNo, order.Amount)
			}()

			wg.Add(1)
			go func() {
				defer wg.Done()
				socket := l.svcCtx.WebSocketPool.Get()

				business := busService.GetBussById(redis, order.BusinessId)

				if business != nil {

					// 修改累计交易金额
					busService.UpdateMoneyAll(redis, business.Phone, order.Amount)
					moneyAll := busService.GetMoneyAll(redis, business.Phone)

					// 修改今日交易金额
					busService.UpdateMoneyToday(redis, business.Phone, order.Amount)
					moneyToday := busService.GetMoneyToday(redis, business.Phone)

					fd, err := busService.GetBussSocket(redis, business.Phone)
					if err == nil {

						voice = "微信收款" + strconv.Itoa(result) // 收款信息

						d := map[string]string{
							"voice":       voice,
							"money_all":   strconv.Itoa(moneyAll),
							"money_today": strconv.Itoa(moneyToday),
						}

						jsonD, _ := json.Marshal(d)

						data := map[string]string{
							"to_id": fd,
							"data":  string(jsonD),
							"code":  "sendMsg",
						}

						jsonD, _ = json.Marshal(data)
						err = socket.WriteMessage(websocket.TextMessage, jsonD)
					}
				}

			}()

		}

	}

	return &types.ResponseWxNotify{
		Code: "SUCCESS",
	}, nil
}
